package com.vpen.iot.controller;

import org.apache.commons.codec.digest.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class LicenseSigner {

    public static void main(String[] args) {
        try {
            // 读取私钥
            String privateKeyPath = "ca.key";
            RSAPrivateKey privateKey = loadPrivateKey(privateKeyPath);

            // 计算HASH值，这里使用SHA1摘要
            String licensePart = "license part example";  // 替换为实际的license部分
            byte[] licensePartBytes = licensePart.getBytes(StandardCharsets.UTF_8);
            byte[] digest = DigestUtils.sha1(licensePartBytes);  // 使用Apache Commons Codec的SHA1

            // 使用私钥对HASH值进行签名
            byte[] signature = signWithPrivateKey(privateKey, digest);

            // 将签名结果和licensePart编码为Base64
            String sigResultsBase64 = Base64.getEncoder().encodeToString(signature);
            String licensePartBase64 = Base64.getEncoder().encodeToString(licensePartBytes);

            // 验证签名
            RSAPublicKey publicKey = loadPublicKey("ca.crt"); // 替换为实际的公钥路径
            verifySignature(publicKey, sigResultsBase64, licensePartBase64);

            // 构建最终结果
            String licenseId = "yourLicenseId";  // 替换为实际的licenseId
            String certBase64 = "yourCertBase64"; // 替换为实际的证书Base64编码
            String result = licenseId + "-" + licensePartBase64 + "-" + sigResultsBase64 + "-" + certBase64;
            System.out.println(result);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 加载私钥
    private static RSAPrivateKey loadPrivateKey(String privateKeyPath) throws Exception {
        java.nio.file.Path path = java.nio.file.Paths.get(privateKeyPath);
        byte[] keyBytes = java.nio.file.Files.readAllBytes(path);
        String privateKeyContent = new String(keyBytes, StandardCharsets.UTF_8);
        privateKeyContent = privateKeyContent.replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");
        byte[] decoded = Base64.getDecoder().decode(privateKeyContent);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(decoded));
    }

    // 使用私钥进行签名
    private static byte[] signWithPrivateKey(RSAPrivateKey privateKey, byte[] data) throws Exception {
        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }

    // 加载公钥
    private static RSAPublicKey loadPublicKey(String publicKeyPath) throws Exception {
        java.nio.file.Path path = java.nio.file.Paths.get(publicKeyPath);
        byte[] keyBytes = java.nio.file.Files.readAllBytes(path);
        String publicKeyContent = new String(keyBytes, StandardCharsets.UTF_8);
        publicKeyContent = publicKeyContent.replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "").replaceAll("\\s+", "");
        byte[] decoded = Base64.getDecoder().decode(publicKeyContent);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(decoded));
    }

    // 验证签名
    private static void verifySignature(RSAPublicKey publicKey, String sigResultsBase64, String licensePartBase64) throws Exception {
        byte[] signatureBytes = Base64.getDecoder().decode(sigResultsBase64);
        byte[] licensePartBytes = Base64.getDecoder().decode(licensePartBase64);

        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initVerify(publicKey);
        signature.update(licensePartBytes);
        if (!signature.verify(signatureBytes)) {
            throw new SecurityException("Signature verification failed");
        }
    }
}
